package jdos.hardware;

import jdos.util.Ptr;

public class VGA {
	public static final boolean newType = false;
	
    //#define VGA_KEEP_CHANGES
    public static final int VGA_CHANGE_SHIFT = 9;

    public static final int M_EGA = 2;
    public static final int M_TEXT = 9;

    public static class VGA_Internal {
        public boolean attrindex;
    }

    public static class VGA_Config {
        public /*Bitu*/int cursor_start;
        public /*Bit8u*/short read_mode;
        public /*Bit8u*/short write_mode;
        public /*Bit8u*/short raster_op;
        public /*Bit8u*/short color_dont_care;
        public /*Bit8u*/short color_compare;
    }

    public static class VGA_Draw {

        public /*Bit8u*/byte[] font = new byte[64*1024];
        public /*Bit8u*/Ptr[] font_tables = new Ptr[2];
        //public boolean blink;
        public static class Cursor {
            /*Bitu*/public int address;
            /*Bit8u*/public short sline,eline;
            /*Bit8u*/public boolean enabled;
        }
        public Cursor cursor = new Cursor();
        public boolean vga_override;
    }

    public static class VGA_HWCURSOR {
        public /*Bit8u*/short curmode;
        public /*Bit16u*/int originx, originy;
        public /*Bit8u*/short fstackpos, bstackpos;
        public /*Bit8u*/Ptr forestack = new Ptr(4);
        public /*Bit8u*/Ptr backstack = new Ptr(4);
        public /*Bit16u*/int startaddr;
        public /*Bit8u*/short posx, posy;
        public /*Bit8u*/short[][] mc=new short[64][64];
    }

    public static class VGA_Seq {
        public /*Bit8u*/short index;
        public /*Bit8u*/short reset;
        public /*Bit8u*/byte map_mask;
    }

    public static class RGBEntry  {
        public /*Bit8u*/short red;
        public /*Bit8u*/short green;
        public /*Bit8u*/short blue;
    }

    public static class VGA_Latch {
        public /*Bit32u*/int d;
        public /*Bit8u*/short b(int index) {
            switch (index) {
                case 0:
                    return (short)(d & 0xFF);
                case 1:
                    return (short)((d >> 8) & 0xFF);
                case 2:
                    return (short)((d >> 16) & 0xFF);
                case 3:
                    return (short)((d >> 24) & 0xFF);
            }
            return 0;
        }
    }

    public static class VGA_Changes {
        //Add a few more just to be safe
        public /*Bit8u*/Ptr	map; /* allocated dynamically: [(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32] */
        public /*Bit8u*/short	checkMask, frame, writeMask;
        public boolean	active;
        public /*Bit32u*/int  clearMask;
        public /*Bit32u*/int	start, last;
        public /*Bit32u*/int	lastAddress;
    }

    static public class VGA_Type {
        /*Bit8u*/short misc_output;
        public VGA_Draw draw = new VGA_Draw();
        public VGA_Config config = new VGA_Config();
        public VGA_Internal internal = new VGA_Internal();
    /* Internal module groups */
        public VGA_Seq seq = new VGA_Seq();
    }

    /* Support for modular SVGA implementation */
    /* Video mode extra data to be passed to FinishSetMode_SVGA().
       This structure will be in flux until all drivers (including S3)
       are properly separated. Right now it contains only three overflow
       fields in S3 format and relies on drivers re-interpreting those.
       For reference:
       ver_overflow:X|line_comp10|X|vretrace10|X|vbstart10|vdispend10|vtotal10
       hor_overflow:X|X|X|hretrace8|X|hblank8|hdispend8|htotal8
       offset is not currently used by drivers (useful only for S3 itself)
       It also contains basic int10 mode data - number, vtotal, htotal
       */
    public static class VGA_ModeExtraData {
        public /*Bit8u*/short ver_overflow;
        public /*Bit8u*/short hor_overflow;
        public /*Bitu*/int offset;
        public /*Bitu*/int modeNo;
        public /*Bitu*/int htotal;
        public /*Bitu*/int vtotal;
    }

    // Vector function prototypes
    public static interface tWritePort {
        public void call(/*Bitu*/int reg,/*Bitu*/int val,/*Bitu*/int iolen);
    }
    public static interface tReadPort {
        public /*Bitu*/int call(/*Bitu*/int reg,/*Bitu*/int iolen);
    }
    public static interface tFinishSetMode {
        public void call(/*Bitu*/int crtc_base, VGA_ModeExtraData modeData);
    }
    public static interface tSetClock {
        public void call(/*Bitu*/int which,/*Bitu*/int target);
    }
    public static interface tGetClock {
        public /*Bitu*/int call();
    }
    public static interface tHWCursorActive {
        public boolean call();
    }
    public static interface tAcceptsMode {
        public boolean call(/*Bitu*/int modeNo);
    }

    public static VGA_Type vga;

    public static /*Bit32u*/int[] TXT_FG_Table=new int[16];
    public static /*Bit32u*/int[] ExpandTable=new int[256];
    
    public static /*Bit32u*/int[] FillTable=new int[16];


    public static void VGA_Init() {
        VGA_dac.VGA_SetupDAC();
        VGA_gfx.VGA_SetupGFX();
        VGA_seq.VGA_SetupSEQ();

		if (newType) {
			for (int i = 0; i < 256; i++) {
				int a = (i >> 7) & 0x01;
				int b = (i >> 6) & 0x01;
				int c = (i >> 5) & 0x01;
				int d = (i >> 4) & 0x01;
				int e = (i >> 3) & 0x01;
				int f = (i >> 2) & 0x01;
				int g = (i >> 1) & 0x01;
				int h = (i >> 0) & 0x01;
				int z = a | (b << 4) | (c << 8) | (d << 12) | (e << 16) | (f << 20) | (g << 24) | (h << 28);
		        ExpandTable[i]= z | (z << 1)| (z <<2) | (z << 3);
		    }
		    for (int i=0;i<16;i++) {
		        TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
		        FillTable[i]=
		            ((i & 1)!=0 ? 0x11111111 : 0) |
		            ((i & 2)!=0 ? 0x22222222 : 0) |
		            ((i & 4)!=0 ? 0x44444444 : 0) |
		            ((i & 8)!=0 ? 0x88888888 : 0) ;
		    }
		} else {
	        /*Bitu*/int i,j;
	        for (i=0;i<256;i++) {
	            ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24);
	        }
	        for (i=0;i<16;i++) {
	            TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
	            FillTable[i]=
	                ((i & 1)!=0 ? 0x000000ff : 0) |
	                ((i & 2)!=0 ? 0x0000ff00 : 0) |
	                ((i & 4)!=0 ? 0x00ff0000 : 0) |
	                ((i & 8)!=0 ? 0xff000000 : 0) ;
	        }
		}

    }

    static public void VGA_Init2() {
        vga=new VGA_Type();
    }
}
